package parser

import (
	"gf-xb-api/cwt/filter/model"
	"gf-xb-api/cwt/filter/parser/rule"
	"gf-xb-api/utility/xstr"

	"github.com/gogf/gf/v2/database/gdb"
)

// ConvertObjectToMPAndSort ... 查询包装器和排序
func ConvertObjectToMPAndSort[T any](p *model.PageRequest[T], m *gdb.Model) (queryWrapper *gdb.Model, err error) {
	// 筛选条件
	queryWrapper, err = ConvertObjectToMP(p, m)
	if err != nil {
		return nil, err
	}

	// 排序
	queryWrapper = SortByPageCondition[T](queryWrapper, p.PageCondition)
	return queryWrapper, nil
}

// ConvertObjectToMP ... 查询包装器
func ConvertObjectToMP[T any](p *model.PageRequest[T], m *gdb.Model) (queryWrapper *gdb.Model, err error) {

	// region 清除无效规则和分组

	p = cleanMpPager(p)
	if p == nil {
		return m, nil
	}

	if p.FilterGroup == nil {
		return m, nil
	}

	// endregion

	// region 筛选装饰器

	wb, err := ToWrapper(*p.FilterGroup, m)
	if err != nil {
		return nil, err
	}

	if wb == nil {
		return m, nil
	}

	queryWrapper = m.Where(wb)

	// endregion

	return queryWrapper, nil
}

// SortByPageCondition ... 排序处理
func SortByPageCondition[T any](m *gdb.Model, pageCondition *model.PageCondition) *gdb.Model {

	if m == nil {
		return m
	}

	var pageIndex, pageSize = 1, 10

	if pageCondition == nil {
		return m.Limit(pageSize).Offset((pageIndex - 1) * pageSize)
	}

	// 排序
	if pageCondition.PageIndex > 0 {
		pageIndex = pageCondition.PageIndex
	}

	if pageCondition.PageSize > 0 {
		pageSize = pageCondition.PageSize
	}

	sortConditions := pageCondition.SortConditions
	if len(sortConditions) > 0 {

		for _, sortCondition := range sortConditions {
			field := sortCondition.SortField
			isAsc := sortCondition.ListSortDirection == model.Ascending

			dbFieldName := rule.GetDbFieldName[T](field)

			if isAsc {
				m = m.OrderAsc(dbFieldName)
			} else {
				m = m.OrderDesc(dbFieldName)
			}
		}
	}

	return m.Limit(pageSize).Offset((pageIndex - 1) * pageSize)
}

func cleanMpPager[T any](p *model.PageRequest[T]) *model.PageRequest[T] {
	group := cleanMpFilterGroup(p.FilterGroup)
	if group == nil {
		return nil
	}

	p.FilterGroup = group
	return p
}

func cleanMpFilterGroup[T any](group *model.FilterGroup[T]) *model.FilterGroup[T] {
	groups := group.Groups
	rules := group.Rules

	rules = cleanRules(rules)
	groups = cleanGroups(groups)

	var res = &model.FilterGroup[T]{}

	if len(groups) == 0 && len(rules) == 0 {
		return nil
	}

	res.Rules = rules
	res.Groups = groups
	res.Operate = group.Operate

	return res
}

// cleanGroups ... 递归清除无效分组
func cleanGroups[T any](groups []*model.FilterGroup[T]) []*model.FilterGroup[T] {

	if len(groups) == 0 {
		return groups
	}

	for i := 0; i < len(groups); {

		group := groups[i]

		if group == nil {
			groups = append(groups[:i], groups[i+1:]...)
			continue
		}

		childrenGroup := group.Groups
		rules := group.Rules

		if len(rules) > 0 {
			rules = cleanRules(rules)
		}

		if childrenGroup != nil {
			childrenGroup = cleanGroups(childrenGroup)
		}

		if len(rules) == 0 && len(childrenGroup) == 0 {
			groups = append(groups[:i], groups[i+1:]...)
			continue
		}

		i = i + 1
	}

	return groups
}

// cleanRules ... 递归清除无效规则
func cleanRules[T any](rules []*model.FilterRule[T]) []*model.FilterRule[T] {

	if len(rules) == 0 {
		return rules
	}

	for i := 0; i < len(rules); {
		rule := rules[i]

		if xstr.IsBlank(rule.Value) && len(rule.Datas) == 0 {
			rules = append(rules[:i], rules[i+1:]...)
			continue
		}

		i = i + 1
	}

	return rules
}
